Debugging of software programs is fundamentally about tracing effects back to their causes. However, traditional debuggers merely monitor a program's forward execution and are not well suited to the debugging task. Debugging also requires information about the program state(s) in the past. Saving all programming history is such an overwhelming task that so much recording of the past is discarded, often in a FIFO format. Upon discarding, a trace to the past, and often the key to diagnosing a defect, is lost forever thereby decreasing chances of debugging success. Altogether, there exists no technology today that provides a debugger with the following desirable properties:
1. Comprehensive recording. The capture of enough information from a single run of the debuggee program that nearly every detail of the program state during the run can be reconstructed without having to run the program again. In turn, this allows one to hoist “run the program” out of the loop of a programmer's debugging activity. Comprehensiveness is also desirable in that it aids debugging of non-deterministic programs such that, once a bug has manifested itself once, users can diagnose it and permanently eliminate its root cause.
2. Efficient state reconstruction. The ability of a debugger to reconstruct program states at any point in time with a cost proportional to the amount of states reconstructed, but independent of any actual time point chosen. In the prior art, this was problematic for replay-based techniques, which tended to have a cost proportional to the differences in time points of interest.
3. Efficient reverse dataflow. As is known, a fundamental debugging analysis includes determining when and where was a wrong value X at time T set. It is then desirable to efficiently analyze this, but at a cost independent of the difference in time between T and when X was set.
4. Additional queries. The ability of a debugger to efficiently answer questions other than traditional inquiries posed above, such as “when was the last execution of program point P (before time T).”
5. Practicality. The ability of a debugger to find usability with as many programmers as possible. For this, it should then have ability to run on PC-class hardware, supporting standard operating systems, languages, and runtime systems, etc. It should also be able to handle large complex programs, since many of the hardest debugging problems exist in the larger, more popular programs readily accessible to hackers.
6. Reasonable overhead. The ability of a debugger to record the past (so that users can find and diagnose bugs) with minimal expense of space and time requirements for recording. It should also avoid exhausting the user's hardware or patience. To the extent automated testing is available for recording the past, it should be able to run unattended.
To this end, the prior art fails and needs presently exist to meet all or most of the above-requirements. Naturally, any improvements should further contemplate good engineering practices, such as relative inexpensiveness, stability, ease of implementation, low complexity, etc.